package com.basic.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.basic.backend.mapper.UserMapper;
import com.basic.backend.model.dto.analysis.AnalysisStatsDTO;
import com.basic.backend.model.entity.User;
import com.basic.backend.model.vo.IndexStatisticsVO;
import com.basic.backend.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.queue.CircularFifoQueue;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.software.os.OSFileStore;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class IndexServiceImpl implements IndexService {

    @Resource
    private ArticlesService articlesService;

    @Resource
    private UserService userService;

    @Resource
    private ArticleImagesService articleImagesService;

    @Resource
    private ArticleVideosService articleVideosService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private AnalysisService analysisService;

    private final SystemInfo systemInfo = new SystemInfo();
    private final CentralProcessor processor = systemInfo.getHardware().getProcessor();

    // 内存历史数据存储（保留最近10个点，每6秒采集一次）
    private final CircularFifoQueue<Double> memoryHistoryQueue = new CircularFifoQueue<>(10);

    // 每6秒采集一次内存数据（与定时任务同步）
    @Scheduled(fixedRate = 6000)
    public void collectMemoryUsage() {
        try {
            GlobalMemory memory = systemInfo.getHardware().getMemory();
            double used = (memory.getTotal() - memory.getAvailable()) / 1e9;  // 转换为GB
            double total = memory.getTotal() / 1e9;
            double percent = (used / total) * 100;

            synchronized (memoryHistoryQueue) {
                memoryHistoryQueue.add(Math.round(percent * 10) / 10.0);
            }
        } catch (Exception e) {
            log.error("内存数据采集失败", e);
        }
    }

    @Override
    public IndexStatisticsVO getSystemStatistics() {
        IndexStatisticsVO vo = new IndexStatisticsVO();

        // 基础统计
        vo.setTotalArticles(articlesService.count() + articleImagesService.count() +articleVideosService.count());
        vo.setTotalUsers(userService.count());
        vo.setCheckedArticles(analysisService.count());
        vo.setNewUsers(getRecentUsers(24));

        // 比例计算
        calculateRatios(vo);

        // 系统监控
        collectSystemMetrics(vo);

        // 内存历史数据
        synchronized (memoryHistoryQueue) {
            vo.setMemoryHistory(new ArrayList<>(memoryHistoryQueue));
        }

        return vo;
    }

    private Long getRecentUsers(int hours) {
        return userMapper.selectCount(new LambdaQueryWrapper<User>()
                .ge(User::getCreateTime, LocalDateTime.now().minusHours(hours))
        );
    }

    private void calculateRatios(IndexStatisticsVO vo) {
        AnalysisStatsDTO stats = analysisService.getAnalysisStats();
        BigDecimal total = BigDecimal.valueOf(stats.getTotalChecked());

        if(total.compareTo(BigDecimal.ZERO) > 0) {
            vo.setTruthRatio(calculatePercentage(stats.getRealCount(), total));
            vo.setAiRatio(calculatePercentage(stats.getAiGeneratedCount(), total));
        } else {
            vo.setTruthRatio("0%");
            vo.setAiRatio("0%");
        }
    }

    private String calculatePercentage(long count, BigDecimal total) {
        return new BigDecimal(count)
                .divide(total, 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100))
                .setScale(2, RoundingMode.HALF_UP) + "%";
    }

    private void collectSystemMetrics(IndexStatisticsVO vo) {
        try {
            // CPU使用率（准确测量）
            double cpuUsage = getCpuUsage();
            vo.setCpuLoad(String.format("%.1f%%", cpuUsage));

            // 内存使用
            collectMemoryUsage(vo);

            // 磁盘使用
            collectDiskUsage(vo);

        } catch (Exception e) {
            log.error("系统指标采集异常", e);
            setDefaultMetrics(vo);
        }
    }

    private double getCpuUsage() {
        try {
            long[] prevTicks = processor.getSystemCpuLoadTicks();
            Thread.sleep(1000); // 等待1秒获取准确率
            double usage = processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100;
            return Math.max(0, Math.min(usage, 100)); // 限制在0-100%
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return -1;
        } catch (Exception e) {
            log.error("CPU数据采集失败", e);
            return -1;
        }
    }

    private void collectMemoryUsage(IndexStatisticsVO vo) {
        GlobalMemory memory = systemInfo.getHardware().getMemory();
        double memTotal = memory.getTotal() / 1e9;
        double memUsed = (memory.getTotal() - memory.getAvailable()) / 1e9;
        vo.setMemoryUsage(String.format("%.1fG/%.1fG", memUsed, memTotal));
    }

    private void collectDiskUsage(IndexStatisticsVO vo) {
        try {
            List<OSFileStore> stores = systemInfo.getOperatingSystem().getFileSystem().getFileStores();
            if (!stores.isEmpty()) {
                OSFileStore store = stores.get(0);
                double total = store.getTotalSpace() / 1e9;
                double free = store.getFreeSpace() / 1e9;
                vo.setDiskUsage(String.format("%.1fG/%.1fG", total - free, total));
            }
        } catch (Exception e) {
            log.error("磁盘数据采集失败", e);
        }
    }

    private void setDefaultMetrics(IndexStatisticsVO vo) {
        vo.setCpuLoad("N/A");
        vo.setMemoryUsage("N/A");
        vo.setDiskUsage("N/A");
    }
}